﻿using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;

namespace LS.Screening.UI.Common
{
    /// <summary>
    /// Http帮助类
    /// </summary>
    public static class ClientHelper
    {
        static string serverName = "";
        static string configPath = Path.Combine(Directory.GetCurrentDirectory(), "user");
        static HttpClient client;

        /// <summary>
        /// 初始化HttpClient
        /// </summary>
        /// <param name="token"></param>
        static void InitHttpClient(string token)
        {
            var baseAddress = ClientConfig.Instance.ServerUrl;
            client = new HttpClient(new HttpClientHandler
            {
                ServerCertificateCustomValidationCallback = (a, b, c, d) => true,
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
            });
            if (baseAddress.Substring(8).Contains("/"))
            {
                var ind = baseAddress.LastIndexOf("/");
                if (ind > 0)
                {
                    serverName = baseAddress.Substring(ind + 1);
                    serverName = serverName.Trim('/');
                    baseAddress = baseAddress.Substring(0, ind);
                }
            }
            client.BaseAddress = new Uri(baseAddress);
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
            if (baseAddress.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
            }
            if (!string.IsNullOrEmpty(token))
            {
                client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + token);
                client.DefaultRequestHeaders.ExpectContinue = false;
            }
        }

        /// <summary>
        /// 读取配置文件
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        public static string ReadConfigTxtLine(int line)
        {
            if (File.Exists(configPath))
            {
                var lines = File.ReadLines(configPath, Encoding.UTF8).ToList();
                if (lines.Count > line) return lines[line];
            }
            return string.Empty;
        }

        /// <summary>
        /// 更新配置文件
        /// </summary>
        /// <param name="line"></param>
        /// <param name="txt"></param>
        public static void SetConfigTxtLine(int line, string txt)
        {
            string path = configPath;
            if (!File.Exists(path))
            {
                File.Create(path).Close();
            }
            var lines = File.ReadLines(path, Encoding.UTF8).ToList();
            if (lines.Count >= line + 1)
            {
                lines[line] = txt;
            }
            else
            {
                var temp = new List<string>();
                for (int i = 0; i <= line; i++)
                {
                    if (i < lines.Count)
                    {
                        temp.Add(lines[i]);
                    }
                    else if (i < line)
                    {
                        temp.Add(string.Empty);
                    }
                    else
                    {
                        temp.Add(txt);
                    }
                }
                lines = temp;
            }
            File.WriteAllLines(path, lines, Encoding.UTF8);
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="account"></param>
        /// <param name="password"></param>
        /// <param name="systemCode"></param>
        /// <param name="appType"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static async Task<string> Login(string account, string password, string systemCode, int appType)
        {
            var requestUrl = "/api/account/login";
            var loginJson = new
            {
                Account = account,
                Password = password,
                AppCode = systemCode,
                AppType = appType
            };
            var content = new StringContent(JsonSerializer.Serialize(loginJson));
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            using (var c = new HttpClient(new HttpClientHandler { ServerCertificateCustomValidationCallback = (a, b, c, d) => true }))
            {
                var baseAddress = ClientConfig.Instance.AuthServerUrl;
                c.BaseAddress = new Uri(baseAddress);
                c.DefaultRequestHeaders.Clear();
                c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                c.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
                if (baseAddress.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
                }
                var resp = await c.PostAsync(requestUrl, content);
                if (resp.StatusCode != HttpStatusCode.OK)
                {
                    throw new Exception("登陆失败，请检查帐号或密码是否正确！" + Environment.NewLine + resp.ReasonPhrase);
                }
                if (resp.Headers.Contains("access-token"))
                {
                    var token = resp.Headers.GetValues("access-token").FirstOrDefault();
                    InitHttpClient(token);
                    return token;
                }
                else
                {
                    var ret = await resp.Content.ReadAsStringAsync();
                    var error = JsonNode.Parse(ret)["message"].GetValue<string>()?.Replace("\"", "");
                    throw new Exception(error);
                }
            }
        }

        /// <summary>
        /// 获取文件
        /// </summary>
        /// <param name="file"></param>
        /// <param name="isSetupFile"></param>
        /// <param name="startPoint"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static async Task<byte[]> ReadFile(string file, bool isSetupFile, int? startPoint, int? length)
        {
            if (client == null) return null;
            var requestUrl = $"{serverName}/api/ClientUpdate/ReadFile?file={file}&isSetupFile={isSetupFile}&startPoint={startPoint}&length={length}";
            var resp = await client.PostAsync(requestUrl, null);
            if (resp.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("请求失败:ReadFile，请检查网络或联系管理员！");
            }
            var ret = await resp.Content.ReadFromJsonAsync<ReturnObject<byte[]>>();
            if (!ret.Success)
                throw new Exception(ret.Message);
            return ret.Data;
        }

        /// <summary>
        /// 获取更新文件
        /// </summary>
        /// <param name="lastUpdateTime"></param>
        /// <returns></returns>
        public static async Task<List<FileDescription>> GetUpdateFiles(DateTime? lastUpdateTime)
        {
            if (client == null) return null;
            var requestUrl = $"{serverName}/api/ClientUpdate/GetUpdateFiles?lastUpdateTime={lastUpdateTime}";
            var resp = await client.PostAsync(requestUrl, null);
            if (resp.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("请求失败:GetUpdateFiles，请检查网络或联系管理员！");
            }
            var ret = await resp.Content.ReadFromJsonAsync<ReturnObject<List<FileDescription>>>();
            if (!ret.Success)
                throw new Exception(ret.Message);
            return ret.Data;
        }

        /// <summary>
        /// 获取安装包
        /// </summary>
        /// <param name="searchPattern"></param>
        /// <returns></returns>
        public static async Task<FileDescription> GetSetupFile(string searchPattern)
        {
            if (client == null) return null;
            var requestUrl = $"{serverName}/api/ClientUpdate/GetSetupFile?searchPattern={searchPattern}";
            var resp = await client.PostAsync(requestUrl, null);
            if (resp.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("请求失败:GetSetupFile，请检查网络或联系管理员！");
            }
            var ret = await resp.Content.ReadFromJsonAsync<ReturnObject<FileDescription>>();
            if (!ret.Success)
                throw new Exception(ret.Message);
            return ret.Data;
        }
    }

    /// <summary>
    /// 更新文件实体类
    /// </summary>
    public class FileDescription
    {
        private string filePath;

        public string Name { get; set; }

        public string FilePath
        {
            get
            {
                return filePath;
            }
            set
            {
                if (value.StartsWith("\\") || value.StartsWith("/"))
                {
                    filePath = value.Substring(1);
                }
                else
                {
                    filePath = value;
                }
            }
        }

        public DateTime UpdateTime { get; set; }

        public int FileSize { get; set; }

        public override string ToString()
        {
            return Name ?? base.ToString();
        }
    }
}
